package org.tinygame.herostory.handler;

import com.google.protobuf.GeneratedMessageV3;
import org.tinygame.herostory.msg.GameMsgProtocol;
import org.tinygame.herostory.util.PackageUtil;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public final class CmdHandlerFactory {

    //私有构造
    private CmdHandlerFactory(){}

    //处理器Map
    private static final Map<Class<?>,ICmdHandler<? extends GeneratedMessageV3>> handlerMap = new ConcurrentHashMap<>();;

    //初始化
    public static void init(){

        Set<Class<?>> classes = PackageUtil.listSubClazz(CmdHandlerFactory.class.getPackage().getName(), true, ICmdHandler.class);

        for (Class<?> clazz : classes){
            //过滤掉abstract
            if((clazz.getModifiers() & Modifier.ABSTRACT) != 0 || (clazz.getModifiers() & Modifier.INTERFACE) != 0){
                continue;
            }
            //获取方法数组
            Method[] methods = clazz.getDeclaredMethods();

            Class<?> msgType = null;

            for (Method method : methods) {
                if(!method.getName().equals("handler")){
                    continue;
                }
                //取出方法中的参数类型 - 多个参数
                Class<?>[] parameterTypes = method.getParameterTypes();

                //如果方法参数不为2，说明不是handler的方法
                if(parameterTypes.length != 2 || !GeneratedMessageV3.class.isAssignableFrom(parameterTypes[1])){
                    continue;
                }

                //遍历参数 - 因无法确定方法在类中的位置，需要过滤掉接口中参数类型
                if(parameterTypes[0].getName().equals("com.google.protobuf.GeneratedMessageV3") || parameterTypes[1].getName().equals("com.google.protobuf.GeneratedMessageV3")){
                    continue;
                }

                msgType = parameterTypes[1];
                break;
            }

            if(null == msgType){
                continue;
            }

            try {
                ICmdHandler<?> cmdHandler = (ICmdHandler<?>) clazz.newInstance();
                System.out.println("初始化添加成功");
                handlerMap.put(msgType,cmdHandler);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    //获取对应类
    public static ICmdHandler<? extends GeneratedMessageV3> create(Class<?> msgClazz){

        if(null == msgClazz){
            return null;
        }

        return handlerMap.get(msgClazz);
    }


}
